/*
 * Copyright (c) 2020 Tenny
 *  typescript-init is licensed under Mulan PSL v2.
 *  You can use this software according to the terms and conditions of the Mulan PSL v2.
 *  You may obtain a copy of Mulan PSL v2 at:
 *           http://license.coscl.org.cn/MulanPSL2
 *  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 *  See the Mulan PSL v2 for more details.
 */
const fs = require('fs');
const fsp = fs.promises;
const path = require('path');
const https = require('https');

const devDepends = [
  { name: '@typescript-eslint/eslint-plugin', version: '2.30.0' },
  { name: '@typescript-eslint/parser', version: '2.30.0' },
  { name: 'clean-css', version: '4.2.3' },
  { name: 'css-loader', version: '3.5.3' },
  { name: 'eslint', version: '6.8.0' },
  { name: 'eslint-config-alloy', version: '3.7.1' },
  { name: 'html-webpack-plugin', version: '4.3.0' },
  { name: 'less', version: '3.11.1' },
  { name: 'less-loader', version: '6.1.0' },
  { name: 'less-plugin-clean-css', version: '1.5.1' },
  { name: 'style-loader', version: '1.2.1' },
  { name: 'ts-loader', version: '7.0.3' },
  { name: 'typescript', version: '3.8.3' },
  { name: 'webpack', version: '4.43.0' },
  { name: 'webpack-cli', version: '3.3.11' },
  { name: 'webpack-dev-server', version: '3.11.0' }
]

/**
 * https GET 请求
 * @param {String} url 请求 url 地址
 */
let get = function (url) {
  return new Promise((resolve, reject) => {
    https.get(url, (res) => {
      let resData = '', statusCode = res.statusCode;
      res.setEncoding('utf8');
      res.on('data', (chunk) => {
        resData += chunk;
      });
      res.on('end', () => {
        if (statusCode >= 200 && statusCode < 300) {
          resolve(JSON.parse(resData));
        } else {
          reject(new Error(statusCode + ' & ' + res.statusText));
        }
      });
    }).on('error', (e) => {
      reject(e);
    });
  });
};

/**
 * 根据应用包名获取应用的详细信息
 * @param {String} packageName 应用包名
 */
function package (packageName) {
  // https://registry.npmjs.org/koa/latest
  return get(`https://registry.npm.taobao.org/${packageName}/latest`)
    .then(function (r) {
      return { name: r.name, version: r.version };
    });
}

/**
 * 验证字符串是否为空
 * @param str               待验证的字符串
 * @param ignoreWhitespace  是否忽略空格(包括空白字符串以及[\r\t\n]之类的制表符)，默认为true
 */
function isBlank (str, ignoreWhitespace) {
  if (ignoreWhitespace === void 0) { ignoreWhitespace = false; }
  if (str == null) {
    return true;
  }
  return (ignoreWhitespace ? str.trim().length : str.length) === 0;
};

/**
 * 文件递归(使用Promise实现)
 * @param {String} filepath 文件路径
 */
function fileRecursion (filepath) {
  return fsp.stat(filepath)
    .then((stats) => {
      if (stats.isDirectory()) {
        return fsp.readdir(filepath);
      }
      return filepath;
    })
    .then((tfs) => {
      if (tfs instanceof Array) {
        return Promise.all(
          tfs.map((file) => {
            return fileRecursion(path.join(filepath, file));
          })
        );
      } else {
        return tfs;
      }
    });
}

/**
 * 遍历文件夹
 * @param {String} filepath 文件路径
 */
function listFilesSync (filepath) {
  return fileRecursion(filepath)
    .then(ds => {
      return ds.join(',').split(',');
    });
}

/**
 * 检查依赖版本项
 */
function checkDependencies () {
  return new Promise(resolve => {
    let dev1 = [], dev2 = [];
    let len = devDepends.length;
    for (let i = 0; i < len; i++) {
      package(devDepends[i].name)
        .then(pka => {
          if (pka.name.startsWith('@')) {
            dev1.push(pka);
          } else {
            dev2.push(pka);
          }
        })
        .catch(() => {
          if (devDepends[i].name.startsWith('@')) {
            dev1.push(devDepends[i]);
          } else {
            dev2.push(devDepends[i]);
          }
        })
        .finally(() => {
          if ((dev1.length + dev2.length) === len) {
            dev1 = dev1.sort((a, b) => a.name.localeCompare(b.name));
            dev2 = dev2.sort((a, b) => a.name.localeCompare(b.name));
            dev = dev1.concat(dev2);
            resolve({ dev, len });
          }
        })
    }
  });
}

/**
 * 遍历文件夹
 * @param {string} filepath 文件路径
 * @param {function} fn     遍历到文件后的回调函数
 */
function listFiles(filepath, fn) {
  fs.readdir(filepath, function (err, files) {
    for (let file of files) {
      let currFilePath = path.join(filepath, file);
      fs.stat(currFilePath, function (err, stat) {
        if (stat.isDirectory()) {
          listFIles(currFilePath, fn);
        } else {
          fn(currFilePath);
        }
      });
    }
  });
}

module.exports = {
  isBlank,
  listFiles,
  package,
  checkDependencies
}